//
//  WJFontManager.swift
//  PDFSign
//
//  Created by 李永彬 on 2025/9/27.
//

import UIKit
import CoreText

class WJFontManager {
    
    // MARK: - 单例模式
    static let shared = WJFontManager()
    private init() {}
    
    // MARK: - 路径管理
    private let fontsDirectoryName = "Fonts"
    
    /// 获取沙盒中的字体目录URL
    var sandboxFontsDirectoryURL: URL {
        let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        return documentsURL.appendingPathComponent(fontsDirectoryName)
    }
    
    /// 获取项目同级Fonts目录的URL（开发阶段使用）
    var projectFontsDirectoryURL: URL? {
        guard let projectPath = Bundle.main.bundlePath.components(separatedBy: "/Build/Products").first else {
            return nil
        }
        let projectURL = URL(fileURLWithPath: projectPath)
        
        return projectURL.deletingLastPathComponent().appendingPathComponent(fontsDirectoryName)
    }
    
    // MARK: - 公共方法
    
    /// 获取所有可用的字体文件信息
    func saveFontFilesToDatabase() {
        let fileManager = FileManager.default
        let fontsURL = sandboxFontsDirectoryURL
        
        guard fileManager.fileExists(atPath: fontsURL.path) else {
            return
        }
        
        do {
            let fileURLs = try fileManager.contentsOfDirectory(at: fontsURL, includingPropertiesForKeys: [.nameKey, .fileSizeKey, .creationDateKey], options: .skipsHiddenFiles)

            for fileURL in fileURLs {
                if self.isFontFile(fileURL) {
                    var fileSize = 0
                    do {
                        let resources = try fileURL.resourceValues(forKeys: [.fileSizeKey, .creationDateKey])
                        fileSize = Int(resources.fileSize ?? 0)
                    } catch {

                    }
                    let fontFile = WJFontFile()
                    fontFile.filePath = fontsDirectoryName
                    fontFile.fileName = fileURL.lastPathComponent
                    fontFile.fileSize = fileSize
                   let _ = try? fontFile.save()
                }
            }
        } catch {
            print("读取字体文件失败: \(error)")
        }
    }
    
    /// 动态加载字体并生成预览图
    func loadFontWithPreview(_ fontFile: WJFontFile, previewText: String = "AaBbCc", completion: @escaping (WJFontInfo?, Error?) -> Void) {
        DispatchQueue.global(qos: .userInitiated).async {
            do {
                let documentURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
                let fileURL = documentURL.appendingPathComponent(fontFile.filePath).appendingPathComponent(fontFile.fileName)
                let fontData = try Data(contentsOf: fileURL)
                
                guard let dataProvider = CGDataProvider(data: fontData as CFData),
                      let cgFont = CGFont(dataProvider) else {
                    DispatchQueue.main.async {
                        completion(nil, NSError(domain: "WJFontManager", code: -1, userInfo: [NSLocalizedDescriptionKey: "字体文件格式错误"]))
                    }
                    return
                }
                
                // 获取字体名称（无论是否注册都需要）
                guard let postScriptName = cgFont.postScriptName as String? else {
                    DispatchQueue.main.async {
                        completion(nil, NSError(domain: "WJFontManager", code: -2, userInfo: [NSLocalizedDescriptionKey: "无法获取字体名称"]))
                    }
                    return
                }
                
                var registrationError: Error?
                
                // 检查字体是否已经注册
                if !self.isFontRegistered(postScriptName) {
                    // 动态注册字体（只有未注册时才注册）
                    var registerError: Unmanaged<CFError>?
                    if !CTFontManagerRegisterGraphicsFont(cgFont, &registerError) {
                        if let error = registerError?.takeRetainedValue() {
                            registrationError = error
                        } else {
                            registrationError = NSError(domain: "WJFontManager", code: -3, userInfo: [NSLocalizedDescriptionKey: "字体注册失败"])
                        }
                    } else {
                        print("✅ 新注册字体: \(postScriptName)")
                    }
                } else {
                    print("ℹ️ 字体已注册，直接使用: \(postScriptName)")
                }
                
                // 无论注册成功与否，都尝试创建字体信息（字体可能之前已注册）
                if let uifont = UIFont(name: postScriptName, size: 18.0) {
                    let thumbnail = self.generateFontThumbnail(fontName: postScriptName, previewText: previewText)
                    
                    let fontInfo = WJFontInfo(
                        fileInfo: fontFile,
                        postScriptName: postScriptName,
                        fullName: uifont.fontName,
                        thumbnail: thumbnail,
                        isRegistered: true
                    )
                    
                    DispatchQueue.main.async {
                        if let error = registrationError {
                            // 注册失败，但有备用的字体信息
                            print("⚠️ 字体注册失败但可使用已注册版本: \(error.localizedDescription)")
                            completion(fontInfo, nil)
                        } else {
                            completion(fontInfo, nil)
                        }
                    }
                    
                } else {
                    // 无法创建UIFont，说明字体完全不可用
                    DispatchQueue.main.async {
                        if let error = registrationError {
                            completion(nil, error)
                        } else {
                            completion(nil, NSError(domain: "WJFontManager", code: -4, userInfo: [NSLocalizedDescriptionKey: "字体无法使用"]))
                        }
                    }
                }
                
            } catch {
                DispatchQueue.main.async {
                    completion(nil, error)
                }
            }
        }
    }

    /// 检查字体是否已经注册
    private func isFontRegistered(_ fontName: String) -> Bool {
        return UIFont.familyNames.contains { familyName in
            UIFont.fontNames(forFamilyName: familyName).contains(fontName)
        }
    }
    
    /// 卸载字体
    func unloadFont(_ fontInfo: WJFontInfo) -> Bool {
        guard let fontURL = getFontURL(for: fontInfo.fileInfo.fileName) else { return false }
        
        var error: Unmanaged<CFError>?
        let success = CTFontManagerUnregisterFontsForURL(fontURL as CFURL, .process, &error)
        
        if let error = error?.takeRetainedValue() {
            print("卸载字体失败: \(error)")
        }
        
        return success
    }
    
    // MARK: - 私有方法
    
    /// 复制字体文件到沙盒
    func copyFolderToSandbox() {
        // 1. 获取.app包内的文件夹路径
        guard let sourceFolderPath = Bundle.main.path(forResource: fontsDirectoryName, ofType: nil) else {
            print("源文件夹未找到！")
            return
        }
        
        // 2. 获取沙盒目录路径（Documents为例）
        let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
        let targetFolderURL = documentsURL.appendingPathComponent(fontsDirectoryName)
        
        // 创建目标目录（如果不存在）
        do {
            try FileManager.default.createDirectory(at: targetFolderURL, withIntermediateDirectories: true, attributes: nil)
        } catch {
            print("创建目标目录失败: \(error)")
            return
        }
        
        // 3. 递归复制文件夹内容
        copyFolder(from: URL(fileURLWithPath: sourceFolderPath), to: targetFolderURL)
        saveFontFilesToDatabase()
    }
     
    /// 递归复制文件夹内容
    func copyFolder(from sourceURL: URL, to targetURL: URL) {
        do {
            // 获取源文件夹内容列表
            let contents = try FileManager.default.contentsOfDirectory(at: sourceURL, includingPropertiesForKeys: nil)
            
            for itemURL in contents {
                let itemName = itemURL.lastPathComponent
                let targetItemURL = targetURL.appendingPathComponent(itemName)
                
                // 如果是目录，递归复制
                if itemURL.hasDirectoryPath {
                    try FileManager.default.createDirectory(at: targetItemURL, withIntermediateDirectories: true, attributes: nil)
                    copyFolder(from: itemURL, to: targetItemURL)
                }
                // 如果是文件，直接复制
                else {
                    try FileManager.default.copyItem(at: itemURL, to: targetItemURL)
                }
            }
            print("文件夹复制成功！")
        } catch {
            print("复制失败: \(error)")
        }
    }
    /// 检查是否为字体文件
    private func isFontFile(_ url: URL) -> Bool {
        let fontExtensions = ["ttf", "otf", "ttc", "otc", "woff", "woff2"]
        return fontExtensions.contains(url.pathExtension.lowercased())
    }
    
    /// 生成字体预览图
    func generateFontThumbnail(
        fontName: String,
        previewText: String = "AaBbCc",
        size: CGSize = signatureBoxSize,
        maxFontSize: CGFloat = 24,
        minFontSize: CGFloat = 8
    ) -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(size, false, UIScreen.main.scale)
        defer { UIGraphicsEndImageContext() }
        
        guard let context = UIGraphicsGetCurrentContext() else { return nil }
        
        // 背景填充
        UIColor.clear.setFill()
        context.fill(CGRect(origin: .zero, size: size))
        
        // 边框
        UIColor.clear.setStroke()
        context.setLineWidth(1)
        context.stroke(CGRect(x: 0.5, y: 0.5, width: size.width - 1, height: size.height - 1))
        
        // 计算合适的字体大小
        let optimalFontSize = calculateOptimalFontSize(
            text: previewText,
            fontName: fontName,
            maxSize: size.insetBy(dx: 30, dy: 30),
            maxFontSize: maxFontSize,
            minFontSize: minFontSize
        )
        
        guard let font = UIFont(name: fontName, size: optimalFontSize) else { return nil }
        
        let attributes: [NSAttributedString.Key: Any] = [
            .font: font,
            .foregroundColor: UIColor.black
        ]
        
        let text = NSAttributedString(string: previewText, attributes: attributes)
        let textSize = text.size()
        
        let textRect = CGRect(
            x: round((size.width - textSize.width) / 2),
            y: round((size.height - textSize.height) / 2),
            width: textSize.width,
            height: textSize.height
        )
        
        text.draw(in: textRect)
        
        return UIGraphicsGetImageFromCurrentImageContext()
    }

    /// 计算最佳字体大小
    private func calculateOptimalFontSize(
        text: String,
        fontName: String,
        maxSize: CGSize,
        maxFontSize: CGFloat = 24,
        minFontSize: CGFloat = 8
    ) -> CGFloat {
        
        var fontSize = maxFontSize
        
        while fontSize >= minFontSize {
            guard let font = UIFont(name: fontName, size: fontSize) else { break }
            
            let attributes: [NSAttributedString.Key: Any] = [.font: font]
            let textSize = (text as NSString).size(withAttributes: attributes)
            
            if textSize.width <= maxSize.width && textSize.height <= maxSize.height {
                return fontSize
            }
            
            fontSize -= 1
        }
        
        return minFontSize
    }
    
    private func getFontURL(for fileName: String) -> URL? {
        return sandboxFontsDirectoryURL.appendingPathComponent(fileName)
    }
}

// MARK: - 数据模型
struct WJFontInfo {
    let fileInfo: WJFontFile
    let postScriptName: String
    let fullName: String
    let thumbnail: UIImage?
    let isRegistered: Bool
    
    var displayName: String {
        return fullName
    }
}
